import { ipcRenderer } from "electron";
import { IpcMsg } from "@/mdesign-lib/mdesign-main.js";
import { getUid } from "../common";
import { toRaw } from "vue";

export const pickProp = (obj: any, props: string[]) => {
  let result: any = window;
  props.forEach(prop => {
    result = result && result[prop];
    // result[prop] = obj[prop];
  });
  return result;
};
// let uid = 1;
// export const getUid = () => 'id-' + (++uid);
/**
 * 远程方法调用 类 （Remote Method Invoke）
 * 用于在其他独立窗口中异步地调用主窗口方法，并获得返回值
 */
export class RMI {
  /**
   * 远程调用一个主窗口方法，传入方法路径和参数，路径必须是字符串， 参数必须是可序列化的数据（不能传类，函数，循环引用的对象等，最好是字符串，数字，boolean这些基本类型的数据）
   * @param search 方法的路径，如 app.projectManager.getProjectIds
   * @param params 方法的参数，如 [1,2,3]
   * @returns 方法执行后的返回值
   */
  invoke(search: string, params: any[]) {
    let uid = getUid();
    return new Promise(rs => {
      ipcRenderer.send(IpcMsg.RMIInvoke, { uid, search, params });
      const fn = (event: any, res: any) => {
        if (res.uid === uid) {
          rs(res.data);
          ipcRenderer.off(IpcMsg.RMIResponse, fn);
        }
      };
      ipcRenderer.on(IpcMsg.RMIResponse, fn);
    });
  }

  /**
   * 远程窗口调用 action
   * @param actionKey actionKey
   * @param params
   * @returns
   */
  invokeAction(actionKey: string, params: any[]) {
    let uid = getUid();
    return new Promise(rs => {
      ipcRenderer.send(IpcMsg.RMIInvokeAction, { uid, actionKey, params });
      const fn = (event: any, res: any) => {
        if (res.uid === uid) {
          rs(res.data);
          ipcRenderer.off(IpcMsg.RMIResponse, fn);
        }
      };
      ipcRenderer.on(IpcMsg.RMIResponse, fn);
    });
  }

  /**
   * 远程查询主窗口的某个属性，传入属性的路径
   * 查询的结果必须是可序列化的数据，否则会报错
   * @param search 属性的路径 如 app.isActive
   * @returns
   */
  query(search: string) {
    let uid = getUid();
    return new Promise(rs => {
      ipcRenderer.send(IpcMsg.RMIQuery, { uid, search });
      const fn = (event: any, res: any) => {
        if (res.uid === uid) {
          rs(res.data);
          ipcRenderer.off(IpcMsg.RMIResponse, fn);
        }
      };
      ipcRenderer.on(IpcMsg.RMIResponse, fn);
    });
  }

  async doInvokeAction(params: { actionKey: string; uid: string; params: any[] }) {
    const action = window.app.actionManager.getAction(params.actionKey);
    if (!action) {
      ipcRenderer.send(IpcMsg.RMIResponse, { uid: params.uid, data: null, error: true, message: `未找到 action ${params.actionKey}` });
      return;
    }
    try {
      const res2 = await action?.run(...params.params);
      ipcRenderer.send(IpcMsg.RMIResponse, { uid: params.uid, data: toRaw(res2) });
    } catch (error) {
      console.error(error);

      ipcRenderer.send(IpcMsg.RMIResponse, { uid: params.uid, data: null, error: true, message: (error as any) && (error as any).message });
    }
  }

  /**
   * 主窗口中用于接收自窗口的调用请求，执行对应的函数， 只在主窗口的MApp里监听并执行
   * @param params
   */
  async doInvoke(params: { search: string; uid: string; params: any[] }) {
    const names = params.search.split(".");
    const methodName = names.pop() as string;
    const res = pickProp(window, names);
    try {
      const res2 = await res[methodName](...params.params);
      ipcRenderer.send(IpcMsg.RMIResponse, { uid: params.uid, data: toRaw(res2) });
    } catch (error) {
      console.error(error);

      ipcRenderer.send(IpcMsg.RMIResponse, { uid: params.uid, data: null, error: true, message: (error as any) && (error as any).message });
    }
  }

  /**
   * 主窗口中用于接收自窗口的调用请求，只在主窗口的MApp里监听并执行，返回查询到的数据
   * @param params
   */
  async doQuery(params: { search: string; uid: string }) {
    try {
      const names = params.search.split(".");
      const res = pickProp(window, names);

      ipcRenderer.send(IpcMsg.RMIResponse, { uid: params.uid, data: toRaw(res) });
    } catch (error) {
      console.error(error);

      ipcRenderer.send(IpcMsg.RMIResponse, { uid: params.uid, data: null, error: true, message: (error as any) && (error as any).message });
    }
    //
  }
}

export const rmi = new RMI();
